layui.define(["laydate", "laytpl", "table", "layer", "tableEdit", "form"], function (exports) {
  "use strict";
  var moduleName = 'tableTree'
    , _layui = layui
    , laytpl = _layui.laytpl
    , $ = _layui.$
    , table = _layui.table
    , layer = _layui.layer
    , tableEdit = _layui.tableEdit
    , editEntity = tableEdit.callbackFn('tableEdit(getEntity)')
    , form = _layui.form;
  //组件用到的css样式
  var thisCss = [];
  thisCss.push('.layui-tableEdit-checked i{background-color:#60b979!important;}');
  thisCss.push('.layui-tableEdit-edit{position:absolute;right:2px;font-size:18px;bottom:8px;z-index:199109084;}');
  thisCss.push('.layui-tableEdit-edge{position:absolute;left:8px;bottom:0;font-size:15x;z-index:1;}');
  thisCss.push('.layui-tableEdit-tab{position:absolute;left:25px;bottom:0;font-size:15px;z-index:19910908445;}');
  thisCss.push('.layui-tableEdit-span {position:absolute;left:0;padding-left:25px;bottom:0;width:100%;z-index: 199109084}');
  thisCss.push('.layui-tableTree-div {height:100%;}');
  var thisStyle = document.createElement('style');
  thisStyle.innerHTML = thisCss.join('\n'), document.getElementsByTagName('head')[0].appendChild(thisStyle);

  var configs = {
    callbacks: {}
    , tableTreeCache: {}
    , isEmpty: function (data) {
      return typeof data === 'undefined' || data === null || data.length <= 0;
    }
    , parseConfig: function (cols, field) {
      var type, data, enabled, dateType, csField;
      cols.forEach(function (ite) {
        ite.forEach(function (item) {
          if (field !== item.field || !item.config) return;
          var config = item.config;
          type = config.type;
          data = config.data;
          enabled = config.enabled;
          dateType = config.dateType;
          csField = config.cascadeSelectField;
        });
      });
      return { type: type, data: data, enabled: enabled, dateType: dateType, cascadeSelectField: csField };
    }
  };


  var TableTree = function () { this.config = {size:'sm',even:true} };
  TableTree.prototype = {
    /**
     * 表格树渲染
     * @param options 表格参数
     * @param isFirstRender 是否首次渲染
     */
    render: function (options, isFirstRender) { 
      var that = this;
      if (isFirstRender) {
        that._done = options.done;
        $.extend(that.config, options);
        var treeConfig = that.config['treeConfig'];
        var done = function (result) {
          if (!result.data) result.data = table.cache[that.config.id] = [];
          configs.tableTreeCache[$(this.elem).attr('id')] = result.data;
          var params = { field: treeConfig.showField, element: this.elem };
          that.initTree(params);
          if (that._done) {
            that._done.call(this, result);
          }
        };
        that.config.done = done;
      } else {
        that.config = options;
      }
      that.tableEntity = table.render(that.config);
    }
    /**
     * 初始化表格树及为表格树注册相关事件
     * @param options
     */
    , initTree: function (options) {
      var data = configs.tableTreeCache[$(options.element).attr('id')];
      this.doInitTree(data, options.field, null, 0);
      this.closeAllTreeNodes();
      this.parseColsConfig();
      //先注销事件
      this.off();
      //注册事件
      this.events();
    }
    /**
     * 初始化表格树
     * @param arr 表格数据data
     * @param field 树状单元格字段
     * @param tr 初始化当前tr元素
     * @param lvl 当前行等级
     */
    , doInitTree: function (arr, field, tr, lvl) {
      var that = this;
      var tableBody = $(that.config.elem).next().find('div.layui-table-body');
      _layui.each(arr, function (key, item) {
        if (lvl === 0) {
          tr = tableBody.find('tr[data-index="' + key + '"]');
          $(tr).attr('tree-id', item[that.config.treeConfig.treeid]);
          var td = $(tr).find('td[data-field="' + field + '"]');
          var _div = td.find('div.layui-table-cell');
          var span = _div.find('span.layui-tableEdit-span');
          var text = item[that.config.treeConfig.showField]; text = configs.isEmpty(text) ? "" : text;
          !span[0] && (_div.text(''), _div.prepend('<div class="layui-tableTree-div"><span class="layui-tableEdit-span">' + text + '</span></div>'));
          if (!td.find('i.layui-tableEdit-edge')[0]) that.addIcon(tr, td, lvl,item.treeList); 
        } else {
          that.addTreeRow(tr, item);
        }
        if (item.treeList) {
          var nextTr = lvl === 0 ? tr : $(tr).next();
          that.doInitTree(item.treeList, field, nextTr, lvl + 1)
        }
      });
    },
    parseColsConfig: function () {
      var that = this; that.config.colsConfig = {};
      that.config.cols.forEach(function (ite) {
        ite.forEach(function (item) {
          if (!item.config) return;
          that.config.colsConfig[item.field] = item.config;
        });
      });
    }
    /**
     *给当前tr新增子节点
     * @param tr 当前节点
     * @param data 子节点数据
     */
    , addTreeRow: function (tr, data) {
      var that = this, lvl = tr.data('lvl');
      lvl = configs.isEmpty(lvl) ? 0 : parseInt(lvl);
      var treeid = that.config.treeConfig.treeid;
      if (configs.isEmpty(data[treeid])) {
        data[treeid] = Number(Math.random().toString().substr(3, 3) + Date.now()).toString(36);
      }
      var newTr = $('<tr data-lvl="' + (lvl + 1) + '" tree-id="' + data[treeid] + '"></tr>');
      tr.after(newTr);
      that.addElementToTr(data, tr, newTr, lvl + 1);
    }
    /**
     * 根据当前treeid获取相关数据
     * @param arr 表格树数据
     * @param uniqueTreeid 当前treeid值
     * @returns {*}
     */
    , getDataByTreeId: function (arr, uniqueTreeid) {
      var treeid = this.config.treeConfig.treeid;
      for (var i = 0; i < arr.length; i++) {
        var item = arr[i];
        if (uniqueTreeid + "" === item[treeid] + "") {
          return item;
        } else {
          if (item.treeList && item.treeList.length > 0) {
            var data = this.getDataByTreeId(item.treeList, uniqueTreeid);
            if (data) return data;
          }
        }
      }
    }
    /**
     * 给当前行添加图标按钮
     * @param tr 当前tr
     * @param td 树状单元格
     * @param lvl 当前tr等级
     */
    , addIcon: function (tr, td, lvl, hasChildren) { 
      var iconClass = this.config.treeConfig.iconClass;
      iconClass = configs.isEmpty(iconClass) ? 'layui-icon-triangle-r' : iconClass;
      iconClass = hasChildren ? iconClass : ''; // 没有子集的去掉箭头图标
      var that = this
        , icon = $('<i class="layui-icon layui-tableEdit-edge ' + iconClass + '"></i>')
        , div = td.find('div.layui-tableTree-div')
        , _div = $('<div class="layui-tableTree-edit"></div>')
        , span = div.children('span.layui-tableEdit-span');
      if (lvl > 0) {
        var spanLeft = lvl * 21 + 25, iconLeft = lvl * 21 + 5;
        // span.css('left', spanLeft + 'px');
        span.css('padding-left', spanLeft + 'px');
        span.css('left', '0');
        icon.css('left', iconLeft + 'px');
      }
      div.append(icon), $(td).append(_div);
      var add = $('<i class="layui-icon layui-icon-add-1 layui-tableEdit-edit"></i>'); _div.append(add);
      var update = $('<i class="layui-icon layui-icon-edit layui-tableEdit-edit"></i>'); _div.append(update)
      var remove = $('<i class="layui-icon layui-icon-delete layui-tableEdit-edit"></i>'); _div.append(remove);
      var sort = $('<i class="layui-icon layui-icon-return layui-tableEdit-edit asc" style="font-size: 16px"></i>'); _div.append(sort);
      _div.hide(); sort.css('transform', 'rotate(90deg)');
      var heightStyle = that.config.size;
      heightStyle = heightStyle ? heightStyle : '';
      if (heightStyle === 'sm') {  //兼容table的size类型
        span.css('bottom', '0px');
        icon.css('bottom', '0px');
        update.css('bottom', '4px');
        add.css('bottom', '4px');
        remove.css('bottom', '4px');
        sort.css('bottom', '4px');
      }
      if (heightStyle === 'lg') {
        span.css('bottom', '-1px');
        icon.css('bottom', '-1px');
        update.css('bottom', '15px');
        add.css('bottom', '15px');
        remove.css('bottom', '15px');
        sort.css('bottom', '15px');
      }
      sort.css('right', '3px'), remove.css('right', '24px'), update.css('right', '48px'), add.css('right', '72px');
    }
    /**
     * 事件注册
     */
    , events: function () {
      var that = this, filter = $(that.config.elem).attr('lay-filter')
        , tableBody = $(this.config.elem).next().find('div.layui-table-body')
        , tableTreeid = $(that.config.elem).attr('id')
        , iconClass = this.config.treeConfig.iconClass
        , showField = that.config.treeConfig.showField;

      //编辑图标事件注册
      tableBody.on('click', 'i.layui-tableEdit-edit', function (e) {
        //_layui.stope(e);
        var isAdd = $(this).hasClass('layui-icon-add-1')
          , isUpdate = $(this).hasClass('layui-icon-edit')
          , treeData = configs.tableTreeCache[tableTreeid]
          , isDelete = $(this).hasClass('layui-icon-delete')
          , isSort = $(this).hasClass('layui-icon-return');
        var tr = $(this).parents('tr');
        var td = $(this).parents('td'), field = td.data('field');
        var treeid = tr.attr('tree-id');
        var data = that.getDataByTreeId(treeData, treeid);
        var lvl = tr.data('lvl');
        lvl = lvl ? lvl : 0;
        if (isAdd) {//新增
          //回调tool(lay-filter)对应的方法 异步/同步获取数据后回调add方法进行新增行
          var thisObj = {
            value: null, data: data, field: field, add: function (newTree) {
              !newTree && (newTree = []);
              newTree = that.removeRepeatData(newTree);//treeid去重
              if (newTree.length <= 0) {
                var thisData = {};
                that.config.cols.forEach(function (item1) {
                  item1.forEach(function (item) {
                    if (item.field) {
                      if (!(item.field in data)) {
                        thisData[item.field] = null;
                      }
                    }
                  });
                });
                newTree.push(thisData);
              }
              that.asyncAddTree(newTree, data, tr, lvl);
              var treeList = data.treeList;
              if (!treeList) treeList = data.treeList = [];
              var count = 0;
              while (count < newTree.length) {
                treeList.push(newTree[count]); count++;
              }
              that.openTreeNode(tr)
            }, event: 'add'
          };
          active.callbackFn.call(td[0], 'tool(' + filter + ')', thisObj);
        }

        //修改
        if (isUpdate) {
          var oldValue = that.parseTempletData(data, field);
          oldValue = oldValue ? oldValue : '';
          editEntity.input({
            element: td[0], oldValue: oldValue, callback: function (res) {
              var thisObj = {
                value: res, data: data, field: field, update: function (fields) {
                  if (!fields) return;
                  for (var key in fields) {
                    data[key] = fields[key];
                    var showValue = that.parseTempletData(data, key);
                    showValue = showValue ? showValue : '';
                    td.find('div.layui-table-cell span.layui-tableEdit-span').text(showValue)
                  }
                }, event: 'edit'
              };
              active.callbackFn.call(td[0], 'tool(' + filter + ')', thisObj);
            }
          });
        }

        //删除
        if (isDelete) {
          layer.confirm('<div style="color: red;text-align: center;">确定删除吗？</div>', function (index) {
            var thisObj = {
              value: null, data: data, field: field, event: 'del', del: function () {
                var lvl = tr.data('lvl'); lvl = lvl ? lvl : 0;
                //删除页面隐藏的树
                that.removeChildren(tr, lvl);
                //清楚缓存中的数据
                that.clearCacheData(data);
                tr.remove();
              }
            };
            active.callbackFn.call(td[0], 'tool(' + filter + ')', thisObj);
            layer.close(index);
          });
        }

        //排序 => 根据tree-id进行排序
        if (isSort) {
          var icon = $(this);
          var isAsc = icon.hasClass('asc');
          isAsc ? (icon.removeClass('asc'), icon.css('transform', 'rotate(-90deg)'), icon.addClass('desc'))
            : (icon.removeClass('desc'), icon.css('transform', 'rotate(90deg)'), icon.addClass('asc'));
          that.exeTreeNodesSort(tr, that.config.treeConfig.treeid, isAsc);
        }
      });

      table.on('checkbox(' + filter + ')', function (obj) {
        var thisInput = this
          , treeData = configs.tableTreeCache[tableTreeid];
        var tr = $(thisInput).parents('tr'), lvl = tr.data('lvl');
        lvl = lvl ? lvl : 0;
        obj.type === 'one' && function () {
          that.setChildNodeChecked(tr, lvl, obj.checked);
          that.setSupperNodeChecked(tr, obj.checked);
        }();
        var _treeid = tr.attr("tree-id");
        //注意
        //layui组件获取的obj.data可能不正确
        //所以在此直接以此方式获取 保证取到相对应节点数据
        obj.data = that.getDataByTreeId(treeData, _treeid);
        active.callbackFn.call(this, 'checkbox(' + filter + ')', obj);
      });

      //showField字段单元格点击事件，展开子叶节点
      var SPAN_SELECTOR = 'div.layui-tableTree-div span.layui-tableEdit-span';
      tableBody.on('click', SPAN_SELECTOR, function (e) {
        _layui.stope(e);
        var thisTreeElem = $(this).parents('tr');
        var lvl = thisTreeElem.data('lvl'); lvl = lvl ? lvl : 0;
        var icon = $(this).parents('td').find('i.layui-tableEdit-edge');
        var isShow = icon.hasClass('layui-tableEdit-clicked');
        //关闭或者展开子元素
        that.showOrHideChildrenNodes(thisTreeElem, lvl, !isShow);
        //选择三角图标
        that.rotateFunc(icon, !isShow);
      });
      //展示工具栏
      if (this.config.treeConfig.showToolbar) {
        //操作栏鼠标经过事件
        tableBody.on("mouseenter ", 'td[data-field="' + showField + '"]', function (e) {
          _layui.stope(e)
          tableBody.find('div.layui-tableTree-edit').hide();
          $(this).find('div.layui-tableTree-edit').show();
        });
        tableBody.on("mouseleave", 'td[data-field="' + showField + '"]', function (e) {
          _layui.stope(e)
          tableBody.find('div.layui-tableTree-edit').hide();
        });
      }

      var INPUT_SELECTOR = 'td[data-field="' + showField + '"] input.layui-tableEdit-input';
      tableBody.on('blur', INPUT_SELECTOR, function () {
        $(this).remove();
      });

      var toolEvent = 'tool(' + filter + ')';
      table.on(toolEvent, function (obj) {
        var zthis = this
          , field = $(zthis).data('field')
          , config = that.config.colsConfig[field]
          , treeData = configs.tableTreeCache[tableTreeid];
        obj.field = field;
        if (!config) {
          active.callbackFn.call(zthis, toolEvent, obj); return;
        }
        var callbackFn = function (res) {
          obj.value = Array.isArray(res) ? (res.length > 0 ? res : [{ name: '', value: '' }]) : res;
          active.callbackFn.call(zthis, toolEvent, obj);
        };
        var _treeid = $(zthis.parentNode).attr("tree-id");
        //子节点或表格树删除最上级节点后，layui组件得到的数据就不对了。
        //因此直接用getDataByTreeId函数获取
        obj.data = that.getDataByTreeId(treeData, _treeid);
        obj.update = function (fields) {
          if (!fields) return;
          for (var key in fields) {
            obj.data[key] = fields[key];
            var showValue = that.parseTempletData(obj.data, key);
            showValue = showValue ? showValue : '';
            $(zthis).find('div.layui-table-cell').text(showValue)
          }
        };
        if (config.type === 'select') {
          editEntity.register({ data: config.data, element: zthis, enabled: config.enabled, selectedData: obj.data[field], callback: callbackFn });
        } else if (config.type === 'date') {
          editEntity.date({ dateType: config.dateType, element: zthis, callback: callbackFn });
        } else if (config.type === 'input') {
          editEntity.input({ element: zthis, oldValue: obj.data[field], callback: callbackFn });
        } else if (config.type === 'signedInput') {
          editEntity.signedInput({ element: zthis, oldValue: obj.data[field], callback: callbackFn });
        } else active.callbackFn.call(zthis, toolEvent, obj);
      });

      var SELECTOR = 'div.layui-tableTree-div i.' + iconClass;
      tableBody.on('click', SELECTOR, function (e) {
        _layui.stope(e);
        var tr = $(this).parents('tr')
          , treeData = configs.tableTreeCache[tableTreeid];
        var lvl = tr.data('lvl'); lvl = lvl ? lvl : 0;
        var td = $(this).parents('td')
          , field = td.data('field')
          , treeid = tr.attr('tree-id')
          , data = that.getDataByTreeId(treeData, treeid)
          , thisObj = {
            value: null, data: data, field: field, async: function (asyncTree) {
              that.openTreeNode(tr);
              if (!asyncTree || asyncTree.length === 0) return;
              asyncTree = that.removeRepeatData(asyncTree);
              if (asyncTree.length === 0) return;
              that.asyncAddTree(asyncTree, data, tr, lvl);
              if (!data.treeList) data.treeList = [];
              var count = 0;
              while (count < asyncTree.length) {
                data.treeList.push(asyncTree[count]); count++;
              }
              //图标改回来
              that.openTreeNode(tr);
            }, event: 'async'
          };
        active.callbackFn.call(td[0], 'tool(' + filter + ')', thisObj);
      });
    }, off: function () {
      var tableBody = $(this.config.elem).next().find('div.layui-table-body');
      tableBody.off('click', 'i.layui-tableEdit-edit');
      var SPAN_SELECTOR = 'div.layui-tableTree-div span.layui-tableEdit-span';
      tableBody.off('click', SPAN_SELECTOR);
      var showField = this.config.treeConfig.showField;
      tableBody.off("mouseleave", 'td[data-field="' + showField + '"]');
      var INPUT_SELECTOR = 'td[data-field="' + showField + '"] input.layui-tableEdit-input';
      tableBody.off('blur', INPUT_SELECTOR);
      var iconClass = this.config.treeConfig.iconClass;
      var SELECTOR = 'div.layui-tableTree-div i.' + iconClass;
      tableBody.off('click', SELECTOR);
    }
    /**
     * 过滤treeid重复的节点数据
     * @param data 被过滤的数据
     * @returns {Array}
     */
    , removeRepeatData: function (data) {
      var noRepeatData = [], that = this;
      data.forEach(function (e) {
        if (that.checkedRepeatData(e)) return;//treeid重复则直接过滤
        noRepeatData.push(e);
      });
      return noRepeatData;
    }
    /**
     * 根据obj数据给当前节点新增子叶节点
     * @param obj Array类型 子叶节点数据
     * @param data 当前节点数据
     * @param tr 当前节点tr
     * @param lvl 当前节点等级
     */
    , asyncAddTree: function (obj, data, tr, lvl) {
      var that = this;
      var _treeid_ = that.config.treeConfig.treeid;
      var treepid = that.config.treeConfig.treepid;
      !obj && (obj = []);
      obj.forEach(function (e) {
        e[treepid] = data[_treeid_];
        that.addTreeRow(tr, e);
        if (e.treeList && e.treeList.length > 0) {
          that.asyncAddTree(e.treeList, e, tr.next(), lvl + 1);
        }
      });
      var nextIcon = tr.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
      that.rotateFunc(nextIcon, true);
    }
    /**
     * 按table表格列模板(templet)解析数据
     * @param d 当前节点数据
     * @param field 列字段
     * @returns {*}
     */
    , parseTempletData: function (d, field) {
      var rs = null;
      this.config.cols.forEach(function (item1) {
        item1.forEach(function (item2) {
          if (item2.field === field) {
            var templet = item2.templet;
            if (templet) {
              if (typeof templet === 'string') {
                rs = laytpl($(templet).html()).render(d);
              } else {
                rs = templet(d, field);
              }
            } else {
              rs = d[field];
            }
          }
        });
      });
      return rs;
    }
    /**
     * 清除当前数据
     * @param data 当前数据
     */
    , clearCacheData: function (data) {
      if (!data) return
      var treeid = this.config.treeConfig.treeid;
      var tableTreeid = $(this.config.elem).attr('id');
      var treeData = configs.tableTreeCache[tableTreeid];
      this.clearChildCacheData(treeData, data[treeid]);
    }
    /**
     * 清除当前数据的子叶节点数据
     * @param list 表格树数据
     * @param uniqueTreeid 当前节点treeid字段值
     */
    , clearChildCacheData: function (list, uniqueTreeid) {
      var treeid = this.config.treeConfig.treeid;
      for (var i = 0; i < list.length; i++) {
        var item = list[i];
        if ((uniqueTreeid + "") === (item[treeid] + "")) {
          list.splice(i, 1); break;
        } else {
          if (item.treeList && item.treeList.length > 0) {
            this.clearChildCacheData(item.treeList, uniqueTreeid)
          }
        }
      }
    }
    /**
     * 旋转三角图标
     * @param icon 当前三角图标
     * @param isOpen true为关闭 false打开
     */
    , rotateFunc: function (icon, isOpen) {
      if (!isOpen) {
        icon.css('transform', '');
        icon.removeClass('layui-tableEdit-clicked');
      } else {
        icon.css('transform', 'rotate(90deg)');
        icon.addClass('layui-tableEdit-clicked');
      }
    }
    /**
     * 展开或者关闭当前节点及其叶子节点
     * @param elemTree 当前节点tr
     * @param lvl 当前节点等级
     * @param isShow true打开 false关闭
     */
    , showOrHideChildrenNodes: function (elemTree, lvl, isShow) {
      var nextTreeElem = elemTree.next(), nextlvl = nextTreeElem.data('lvl');
      nextlvl = nextlvl ? nextlvl : 0;
      if (nextTreeElem[0] && nextlvl > lvl) {
        if (isShow) {
          if ((nextlvl - lvl) === 1) {
            nextTreeElem.show();
            var nextIcon = nextTreeElem.find('td[data-field="' + this.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
            if (nextIcon.hasClass('layui-tableEdit-clicked')) {
              nextTreeElem.show();
              this.showTreeNodes(nextTreeElem, nextlvl);
            }
          }
        } else {
          nextTreeElem.hide();
        }
        this.showOrHideChildrenNodes(nextTreeElem, lvl, isShow);
      }
    }
    /**
     * 展开当前节点及其叶子节点
     * @param elemTree 当前节点tr
     * @param lvl 当前节点等级
     */
    , showTreeNodes: function (elemTree, lvl) {
      var nextTreeElem = elemTree.next(), nextlvl = nextTreeElem.data('lvl');
      nextlvl = nextlvl ? nextlvl : 0;
      if (nextTreeElem[0] && nextlvl > lvl) {
        if ((nextlvl - lvl) === 1) {
          nextTreeElem.show();
          var nextIcon = nextTreeElem.find('td[data-field="' + this.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
          if (nextIcon.hasClass('layui-tableEdit-clicked')) {
            nextTreeElem.show();
            this.showTreeNodes(nextTreeElem, nextlvl);
          }
        }
        this.showTreeNodes(nextTreeElem, lvl);
      }
    }
    /**
     * 获取当前节点的父节点
     * @param elem 当前节点tr
     * @param lvl 当前节点等级
     * @returns {null|*|jQuery|*}
     */
    , getParentNode: function (elem, lvl) {
      if (lvl === 0) return null;
      var tr = $(elem)
        , prevElem = tr.prev()
        , prevLvl = prevElem.data('lvl');
      prevLvl = prevLvl ? prevLvl : 0;
      if (lvl - prevLvl === 1) return prevElem;
      return this.getParentNode(prevElem, lvl);
    }
    /**
     * 删除当前节点的叶子节点
     * @param elemTree 当前节点tr
     * @param lvl 当前节点等级
     */
    , removeChildren: function (elemTree, lvl) {
      var nextTreeElem = elemTree.next(), nextlvl = nextTreeElem.data('lvl');
      nextlvl = nextlvl ? nextlvl : 0;
      if (nextTreeElem[0] && nextlvl > lvl) {
        nextTreeElem.remove();
        this.removeChildren(elemTree, lvl);
      }
    }
    /**
     * 判断当前节点数据的treeid是否重复
     * @param data 当前节点数据
     * @returns {boolean}
     */
    , checkedRepeatData: function (data) {
      var treeid = this.config.treeConfig.treeid;
      var tableTreeid = $(this.config.elem).attr('id');
      var treeData = configs.tableTreeCache[tableTreeid];
      var ckeckData = this.getDataByTreeId(treeData, data[treeid]);
      return ckeckData ? true : false;
    }
    /**
     * 	获取选中节点数据
     * @returns {*}
     */
    , getCheckedTreeNodeData: function () {
      var that = this;
      var tableBody = $(this.config.elem).next().find('div.layui-table-body');
      var tableTreeid = $(that.config.elem).attr('id');
      var treeData = configs.tableTreeCache[tableTreeid];
      var checkedElem = tableBody.find('td.layui-table-col-special div.layui-form-checked');
      var dataSet = new Set();
      checkedElem.each(function () {
        var tr = $(this).parents('tr').eq(0);
        var treeid = tr.attr('tree-id');
        var data = that.getDataByTreeId(treeData, treeid);
        dataSet.add(data);
      });
      return Array.from(dataSet);
    }
    /**
     * 获取当前节点的最顶级节点
     * @param elem 当前节点
     * @returns {*}
     */
    , getTopNode: function (elem) {
      var lvl = elem.data('lvl')
        , prevTr = elem.prev();
      lvl = lvl ? lvl : 0;
      if (lvl === 0) return elem;
      return this.getTopNode(prevTr);
    }
    /**
     * 重载表格树
     * @param options
     */
    , reload: function (options) {
      if (options && options.done) {
        this._done = options.done;
      }
      this.render(this.config);
    }
    /**
     * 指定节点或节点id展开节点
     * @param params 节点或节点id
     */
    , openTreeNode: function (params) {
      var that = this;
      var treeid, tr;
      if (typeof params === 'string' || Object.prototype.toString.call(params) === '[object Number]') {
        treeid = params;
        tr = $(that.config.elem).next().find('div.layui-table-body tr[tree-id="' + treeid + '"]');
      } else {
        tr = $(params);
      }
      tr.show();
      var icon = tr.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
      var lvl = tr.data('lvl');
      lvl = lvl ? lvl : 0;
      that.showOrHideChildrenNodes(tr, lvl, true);
      that.rotateFunc(icon, true);
      var parentNode = that.getParentNode(tr, lvl);
      while (parentNode && parentNode[0]) {
        parentNode.show();
        icon = parentNode.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
        lvl = parentNode.data('lvl');
        lvl = lvl ? lvl : 0;
        that.rotateFunc(icon, true);
        parentNode = that.getParentNode(parentNode, lvl);
      }
      var topNode = that.getTopNode(tr);
      that.showOrHideChildrenNodes(topNode, 0, true);
    }
    /**
     * 指定节点或节点id折叠节点
     * @param params 节点或节点id
     */
    , closeTreeNode: function (params) {
      var that = this;
      var treeid, tr;
      if (typeof params === 'string' || Object.prototype.toString.call(params) === '[object Number]') {
        treeid = params;
        tr = $(that.config.elem).next().find('div.layui-table-body tr[tree-id="' + treeid + '"]');
      } else {
        tr = $(params);
      }
      var icon = tr.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
      var lvl = tr.data('lvl');
      lvl = lvl ? lvl : 0;
      that.showOrHideChildrenNodes(tr, lvl, false);
      that.rotateFunc(icon, false);
    }
    /**
     * 展开所有节点
     */
    , openAllTreeNodes: function () {
      var that = this;
      var tableBody = $(this.config.elem).next().find('div.layui-table-body');
      tableBody.find('tr').each(function (e) {
        var tr = $(this);
        var icon = tr.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
        $(this).show();
        that.rotateFunc(icon, true);
      });
    }
    /**
     * 折叠所有节点
     */
    , closeAllTreeNodes: function () {
      var that = this;
      var tableBody = $(this.config.elem).next().find('div.layui-table-body');
      tableBody.find('tr').each(function (e) {
        var tr = $(this);
        var icon = tr.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
        var lvl = tr.data('lvl');
        lvl = lvl ? lvl : 0;
        if (lvl > 0) $(this).hide();
        that.rotateFunc(icon, false);
      });
    }
    /**
     * 表格树节点逐级排序
     * @param options {field:'xxx',desc:true} field：排序字段 desc => true降序、false升序
     * @param treeData 表格树数据
     */
    , sort: function (options, treeData) {
      var that = this;
      treeData.sort(function (o1, o2) {
        var isNum = /(^[-+]?\d+$)|(^[-+]?\d+\.\d+$)/
          , v1 = o1[options.field]
          , v2 = o2[options.field];
        if (isNum.test(v1) && isNum.test(v2)) {
          v1 = parseFloat(v1);
          v2 = parseFloat(v2);
          if (v1 > v2) {
            return 1;
          } else if (v1 < v2) {
            return -1;
          } else {
            return 0;
          }
        } else {
          if (v1 && !v2) {
            return 1;
          } else if (!v1 && v2) {
            return -1;
          }
          (v1 + '').localeCompare(v2 + '', 'zh-CN')
        }
      });
      if (options.desc) {
        treeData.reverse();
      }
      treeData.forEach(function (e) {
        if (e.treeList && e.treeList.length > 0) {
          that.sort(options, e.treeList);
        }
      });
    }
    /**
     * 获取表格树参数配置
     * @returns {*}
     */
    , getTableTreeData: function () {
      var tableTreeid = $(this.config.elem).attr('id');
      var treeData = configs.tableTreeCache[tableTreeid];
      return treeData;
    }
    /**
     * 增加最上级节点 => 单个节点
     * @param data object类型
     */
    , addTopTreeNode: function (data) {
      var that = this;
      var treeid = that.config.treeConfig.treeid;
      var treepid = that.config.treeConfig.treepid;
      var tableTreeid = $(that.config.elem).attr('id')
        , treeData = configs.tableTreeCache[tableTreeid];
      if (treeData.length <= 0) {
        if (!data) {
          data = {};
        }
        that.config.cols.forEach(function (item1) {
          item1.forEach(function (item) {
            if (item.field) {
              if (!(item.field in data)) {
                data[item.field] = null;
              }
            }
          });
        });
        delete data[treepid]; //最上级行不能有treepid
        var url = that.config.url;
        var hasUrl = !configs.isEmpty(url);
        hasUrl && delete that.config.url;
        if (!data[treeid]) {
          data[treeid] = Number(Math.random().toString().substr(3, 3) + Date.now()).toString(36)
        }
        treeData.push(data);
        that.config.data = treeData;
        that.render(that.config);
        if (hasUrl) {
          delete that.config.data;
          that.config.url = url;
        }
        return;
      }

      if (!data || (data && typeof data !== 'object')) {
        data = {};
        for (var key in treeData[0]) {
          data[key] = null;
        }
      }
      delete data[treepid]; //最上级行不能有treepid
      var tr = $(that.config.elem).next().find('div.layui-table-body tr').eq(0);
      if (configs.isEmpty(data[treeid]) || that.checkedRepeatData(data)) {
        data[treeid] = Number(Math.random().toString().substr(3, 3) + Date.now()).toString(36)
      }
      var newTr = $('<tr data-index="' + treeData.length + '" tree-id="' + data[treeid] + '"></tr>');
      tr.before(newTr);
      data['LAY_TABLE_INDEX'] = treeData.length;
      treeData.push(data);
      that.addElementToTr(data, tr, newTr, 0);
      that.rotateFunc(newTr.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge'), true);
    }
    /**
     * 新增行tr
     * @param data 当前行数据
     * @param tr newTr的前一行的tr
     * @param newTr 新增行tr
     * @param lvl 新增行等级
     */
    , addElementToTr: function (data, tr, newTr, lvl) {
      var that = this;
      tr.children('td').each(function () {
        var field = $(this).data('field'), td = null;
        if (field + "" === '0') {
          td = $('<td data-field="0" data-key="1-0-0" class="layui-table-col-special"></td>');
          td.append(this.innerHTML);
        } else {
          var attrsStr = []
            , _divclass = $(this).children('div.layui-table-cell').attr("class")
            , attrs = this.attributes;
          for (var i = 0; i < attrs.length; i++) {
            attrsStr.push(attrs[i].nodeName + '="' + attrs[i].nodeValue + '"');
          }
          var text = that.parseTempletData(data, field); //按模板进行解析
          text = text ? text : '';
          if (field === that.config.treeConfig.showField) {
            td = $('<td ' + attrsStr.join(" ") + '><div class="' + _divclass + '"><div class="layui-tableTree-div"><span class="layui-tableEdit-span">' + text + '</span></div></div></td>');
            that.addIcon(newTr, td, lvl,data.treeList); 
          } else {
            newTr.append('<td ' + attrsStr.join(" ") + '><div class="' + _divclass + '">' + text + '</div></td>');
          }
        }
        newTr.append(td);
      });
      form.render('checkbox');
    }
    /**
     * 指定节点或节点id删除节点及其叶子节点
     * @param params
     */
    , delTreeNode: function (params) {
      if (!params) return;
      var that = this;
      var tableTreeid = $(that.config.elem).attr('id');
      var treeData = configs.tableTreeCache[tableTreeid];
      var treeid, tr;
      if (typeof params === 'string' || Object.prototype.toString.call(params) === '[object Number]') {
        treeid = params;
        tr = $(that.config.elem).next().find('div.layui-table-body tr[tree-id="' + treeid + '"]');
      } else {
        tr = $(params);
        treeid = tr.attr("tree-id");
      }
      var data = that.getDataByTreeId(treeData, treeid);
      var lvl = tr.data('lvl'); lvl = lvl ? lvl : 0;
      //删除页面隐藏的树
      that.removeChildren(tr, lvl);
      //清楚缓存中的数据
      that.clearCacheData(data);
      tr.remove();
    }
    /**
     * 判断当前节点的叶子节点是否有被选中的
     * @param elem 当前节点tr
     * @param lvl 当前节点等级
     * @returns {boolean|*}
     */
    , childNodeHasChecked: function (elem, lvl) {
      var nextTreeElem = elem.next(), nextlvl = nextTreeElem.data('lvl');
      nextlvl = nextlvl ? nextlvl : 0;
      if (nextTreeElem[0] && nextlvl > lvl) {
        var div = $(nextTreeElem).find('td.layui-table-col-special div.layui-form-checkbox');
        return div.hasClass('layui-form-checked') ? true : this.childNodeHasChecked(nextTreeElem, lvl);
      } else {
        return false;
      }
    }
    /**
     * 设置当前节点及其叶子节点为被选中状态
     * @param elem 当前节点
     * @param lvl 当前节点等级
     * @param isChecked true为选中 false为取消选中
     */
    , setChildNodeChecked: function (elem, lvl, isChecked) {
      var nextTreeElem = elem.next(), nextlvl = nextTreeElem.data('lvl');
      nextlvl = nextlvl ? nextlvl : 0;
      if (nextTreeElem[0] && nextlvl > lvl) {
        this.setCheckboxInfo(nextTreeElem, isChecked);
        this.setChildNodeChecked(nextTreeElem, lvl, isChecked);
      }
    }
    /**
     * 设置当前节点的祖辈节点为被选中状态
     * @param elem 当前节点
     * @param isChecked true为选中 false为取消选中
     */
    , setSupperNodeChecked: function (elem, isChecked) {
      var that = this;
      var thisTreeid = $(elem).attr("tree-id")
        , treepid = that.config.treeConfig.treepid
        , tableTreeid = $(that.config.elem).attr('id')
        , treeData = configs.tableTreeCache[tableTreeid]
        , data = that.getDataByTreeId(treeData, thisTreeid)
        , thisTreepid = data[treepid]
        , tableBody = $(that.config.elem).next().find('div.layui-table-body')
        , ptr = tableBody.find('tr[tree-id="' + thisTreepid + '"]');
      var lvl = ptr.data('lvl');
      lvl = lvl ? lvl : 0;
      if (!isChecked) {
        if (!that.childNodeHasChecked(ptr, lvl)) {
          that.setCheckboxInfo(ptr, isChecked);
        }
      } else {
        that.setCheckboxInfo(ptr, isChecked);
      }
      if (lvl === 0) return;
      that.setSupperNodeChecked(ptr, isChecked);
    }
    /**
     * 设置当前节点的选中状态
     * @param elem 当前节点
     * @param isChecked true为选中 false为取消选中
     */
    , setCheckboxInfo: function (elem, isChecked) {
      var div = elem.find('td.layui-table-col-special div.layui-form-checkbox')
        , input = elem.find('td.layui-table-col-special input[type="checkbox"]');
      isChecked ? (div.addClass('layui-form-checked'), input.prop('checked', true))
        : (div.removeClass('layui-form-checked'), input.prop('checked', false));
    }
    /**
     * 关键词检索相关节点
     * @param value 关键词参数
     */
    , keywordSearch: function (value) {
      var that = this;
      var tableBody = $(this.config.elem).next().find('div.layui-table-body');
      var spans = tableBody.find('td[data-field="' + this.config.treeConfig.showField + '"] span.layui-tableEdit-span');
      var tableTreeid = $(that.config.elem).attr('id');
      var treeData = configs.tableTreeCache[tableTreeid];
      var treepid = that.config.treeConfig.treepid;
      that.clearSearch();//每次搜索前都清除标记 然后再进行标记
      tableBody.find("tr").each(function () {
        var tr = $(this);
        if (!tr.is(":hidden")) {
          tr.addClass("layui-tableTree-search");
        }
      });
      var showArr = new Set();
      spans.each(function () {
        var thisValue = this.innerText;
        var tr = $(this).parents('tr').eq(0);
        if (thisValue.indexOf(value) > -1) {
          tr.show();
          var icon = tr.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge')
          tr.hasClass('layui-tableTree-search')
            && !icon.hasClass('layui-tableEdit-clicked')
            && (that.rotateFunc(icon, true), icon.addClass('layui-tableTree-search'));
          var treeid = tr.attr('tree-id');
          showArr.add(treeid)
          var data = that.getDataByTreeId(treeData, treeid);
          var _treepid = data[treepid];
          var parentNode = tableBody.find('tr[tree-id="' + _treepid + '"]');
          while (parentNode[0]) {
            parentNode.show();
            treeid = parentNode.attr('tree-id');
            data = that.getDataByTreeId(treeData, treeid);
            if (data) {
              showArr.add(treeid);
              icon = parentNode.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge')
              parentNode.hasClass('layui-tableTree-search')
                && !icon.hasClass('layui-tableEdit-clicked')
                && (that.rotateFunc(icon, true), icon.addClass('layui-tableTree-search'));
            }
            _treepid = data[treepid];
            parentNode = tableBody.find('tr[tree-id="' + _treepid + '"]');
          }
        } else {
          var treeid = tr.attr('tree-id');
          !showArr.has(treeid) && tr.hide();
        }
      });
    }
    /**
     * 重置表格树到检索前折叠状态
     */
    , clearSearch: function () {
      var that = this;
      var tableBody = $(this.config.elem).next().find('div.layui-table-body');
      var searchTrs = tableBody.find("tr.layui-tableTree-search");
      if (searchTrs.length <= 0) return;
      tableBody.find("tr").each(function () {
        var tr = $(this);
        if (tr.hasClass("layui-tableTree-search")) {
          tr.show();
          var icon = tr.find('td[data-field="' + that.config.treeConfig.showField + '"] i.layui-tableEdit-edge.layui-tableTree-search');
          if (icon[0]) {
            that.rotateFunc(icon, false);
            icon.removeClass('layui-tableTree-search');
            icon.removeClass('layui-tableEdit-clicked');
          }
        } else {
          tr.hide();
        }
        tr.removeClass("layui-tableTree-search");
      });
    }
    /**
     * 刷新当前表格树 => 局部刷新
     * @param data 表格树数据
     * @param tr 当前节点tr
     * @param lvl 当前节点等级
     * @param isFirst 当前节点是否为表格树的第一个节点
     */
    , refreshTableBody: function (data, tr, lvl, isFirst) {
      var that = this;
      var treeid = that.config.treeConfig.treeid;
      var tbody = $(that.config.elem).next().find('div.layui-table-body tbody');
      _layui.each(data, function (index, item) {
        var newTr;
        if (!isFirst) tr = tbody.children(':last-child');
        newTr = lvl <= 0 ? $('<tr data-index="' + index + '" tree-id="' + item[treeid] + '"></tr>')
          : $('<tr data-lvl="' + lvl + '" tree-id="' + item[treeid] + '"></tr>');
        !isFirst ? tr.after(newTr) : (tbody.html(''), tbody.append(newTr));
        isFirst = false;
        that.addElementToTr(item, tr, newTr, lvl);
        if (item.treeList) {
          that.refreshTableBody(item.treeList, newTr, lvl + 1, false);
        }
      });
    }
    /**
     * 刷新当前表格树 => 局部刷新
     * @param data 表格树数据
     */
    , refresh: function (data) {
      var tableTreeid = $(this.config.elem).attr('id');
      var treeid = this.config.treeConfig.treeid;
      var treeData = configs.tableTreeCache[tableTreeid];
      if (data) {
        treeData.splice(0, treeData.length);
        data.forEach(function (e) {
          if (!e[treeid]) {
            e[treeid] = Number(Math.random().toString().substr(3, 3) + Date.now()).toString(36)
          }
          treeData.push(e);
        })
      }
      this.sort({ field: this.config.treeConfig.treeid }, treeData);
      if (treeData.length < -0) return;
      _layui.each(treeData, function (index, item) {
        item['LAY_TABLE_INDEX'] = index;
      });
      var tr = $(this.config.elem).next().find('div.layui-table-body tr').eq(0);
      this.refreshTableBody(treeData, tr, 0, true);
      this.openAllTreeNodes();
      form.render('checkbox');
    }
    /**
     * 根据当前节点id获取叶子节点数据
     * @param treeData 表格树数据
     * @param treeid 当前节点id
     * @param childArr 获取的子节点数据
     */
    , findChildTreeNodes: function (treeData, treeid, childArr) {
      var that = this;
      var treepid = this.config.treeConfig.treepid;
      treeData.forEach(function (item) {
        if (treepid in item) {
          if (item[treepid] + "" === treeid + "") {
            childArr.push(item);
          } else {
            if (item.treeList) {
              that.findChildTreeNodes(item.treeList, treeid, childArr);
            }
          }
        } else {
          if (item.treeList) {
            that.findChildTreeNodes(item.treeList, treeid, childArr);
          }
        }
      });
    }
    /**
     * 指定节点/节点id逐级排序
     * @param params 节点/节点id
     * @param field 排序字段
     * @param isAsc true升序 false降序
     */
    , sortByTreeNode: function (params, field, isAsc) {
      if (!params) return;
      if (typeof params === 'string' || Object.prototype.toString.call(params) === '[object Number]') {
        params = $(this.config.elem).next().find('div.layui-table-body tr[tree-id="' + params + '"]');
      }
      var tr = $(params); tr.show();
      this.exeTreeNodesSort(tr, field, isAsc);
      var lvl = tr.data('lvl'), icon; lvl = lvl ? lvl : 0;
      var parentNode = this.getParentNode(tr, lvl);
      while (parentNode && parentNode[0]) {
        parentNode.show();
        icon = parentNode.find('td[data-field="' + this.config.treeConfig.showField + '"] i.layui-tableEdit-edge');
        lvl = parentNode.data('lvl');
        lvl = lvl ? lvl : 0;
        this.rotateFunc(icon, true);
        parentNode = this.getParentNode(parentNode, lvl);
      }
      var topNode = this.getTopNode(tr);
      this.showOrHideChildrenNodes(topNode, 0, true);
    }
    /**
     * 当前节点叶子节点逐级排序
     * @param tr 当前节点
     * @param field 排序字段
     * @param isAsc true升序 false降序
     */
    , exeTreeNodesSort: function (tr, field, isAsc) {
      var that = this;
      var tableTreeid = $(that.config.elem).attr('id');
      var treeData = configs.tableTreeCache[tableTreeid];
      var lvl = tr.data('lvl'); lvl = lvl ? lvl : 0;
      var brotherArr = [];
      that.findChildTreeNodes(treeData, tr.attr('tree-id'), brotherArr);
      var $treeid = that.config.treeConfig.treeid;
      if (brotherArr.length > 0) {
        that.sort({ field: field, desc: isAsc }, brotherArr);
        brotherArr.forEach(function (item) {
          var ztr = $('tr[tree-id="' + item[$treeid] + '"]'), zlvl = ztr.data('lvl');
          zlvl = zlvl ? zlvl : 0;
          that.removeChildren(ztr, zlvl);
          ztr.remove();
        });
        var sortData = that.getDataByTreeId(treeData, tr.attr('tree-id'));
        that.asyncAddTree(brotherArr, sortData, tr, lvl);
      }
    }
  };

  var active = {
    on: function (event, callback) {
      var filter = event.match(/\((.*)\)$/), eventName = (filter ? (event.replace(filter[0], '') + '_' + filter[1]) : event);
      configs.callbacks[moduleName + '_' + eventName] = callback;
    },
    callbackFn: function (event, params) {
      var filter = event.match(/\((.*)\)$/), eventName = (filter ? (event.replace(filter[0], '') + '_' + filter[1]) : event);
      var key = moduleName + '_' + eventName, func = configs.callbacks[key];
      if (!func) return;
      return func.call(this, params);
    },
    render: function (options) {
      var tableTree = new TableTree();
      tableTree.render(options, true);
      return {
        getTreeOptions: function () {
          return tableTree.config;
        },
        getCheckedTreeNodeData: function () {
          return tableTree.getCheckedTreeNodeData();
        },
        reload: function (options) {
          tableTree.reload(options);
        },
        openTreeNode: function (params) {
          tableTree.openTreeNode(params);
        }
        , closeTreeNode: function (params) {
          tableTree.closeTreeNode(params);
        }
        , closeAllTreeNodes: function () {
          tableTree.closeAllTreeNodes();
        }
        , openAllTreeNodes: function () {
          tableTree.openAllTreeNodes();
        }
        , sort: function (options) {
          var tableTreeid = $(tableTree.config.elem).attr('id');
          var treeData = configs.tableTreeCache[tableTreeid];
          tableTree.sort(options, treeData);
          if (treeData.length < -0) return;
          _layui.each(treeData, function (index, item) {
            item['LAY_TABLE_INDEX'] = index;
          });
          var tr = $(tableTree.config.elem).next().find('div.layui-table-body tr').eq(0);
          tableTree.refreshTableBody(treeData, tr, 0, true);
          tableTree.openAllTreeNodes();
          form.render('checkbox');
        }
        , getTableTreeData: function () {
          return tableTree.getTableTreeData();
        }
        , addTopTreeNode: function (data) {
          tableTree.addTopTreeNode(data);
        }
        , delTreeNode: function (params) {
          tableTree.delTreeNode(params);
        }
        , keywordSearch: function (value) {
          tableTree.keywordSearch(value);
        }
        , clearSearch: function () {
          tableTree.clearSearch();
        }
        , refresh: function (data) {
          tableTree.refresh(data);
        }
        , sortByTreeNode: function (tr, field, isAsc) {
          tableTree.sortByTreeNode(tr, field, isAsc);
        }
      };
    }
  };
  exports(moduleName, active);
});